using System;
using System.Collections.Generic;
using System.Text;
using SP.Parameter;

namespace SP.HwDeferredRS
{
    /// <summary>
    /// A simple base map feature
    /// </summary>
    public class ReflectionMapFusion : AbstractFusion
    {
        public ReflectionMapFusion()
        {
            //AddPreprocessor(new Preprocessor("REFLECTIONMAP_AS_SPECULAR", 0, 1, 1, "Set to 1 for using the reflectionMap as specular."));
            
            // param reflectionMap
            AddParameter(
                new TextureCubeParamter("reflectionMap", "reflectionMapSamp")
                .SetAddressModes(TextureParamter.AddressMode.Clamp, TextureParamter.AddressMode.Clamp, TextureParamter.AddressMode.Clamp)
                .SetSRGBTexture(true)
                .SetUserData("fragment")
                );

            // param reflectionParams
            //AddParameter(new Vec3Parameter("reflectionParams")
            //    .SetX(8.0f).SetY(1.0f).SetZ(0.0f)
            //    .SetDesc("[Power,Multiplier,Bias]"));

            AddParameter(
                new ScalarParameter("reflectance")
                .SetS(0.5f)
                .SetDesc("[0.0 - 2.0], the larger the value, the stronger the reflection effect")
                );
        }

        public override string Name
        {
            get { return "ReflectionMap"; }
        }

        public override string Desc
        {
            get { return ""; }
        }

        public override Stage Stage
        {
            get { return Stage.Relfection; }
        }

        public override int UVChannelCount
        {
            get { return 0; }
        }

        public override void Code(StringBuilder b, string platform)
        {
            AddLine(b, "float s = saturate(dot(pipeline.Normal, -pipeline.ViewDir));");

            //AddLine(b, "#if REFLECTIONMAP_AS_SPECULAR");
            //AddLine(b, "float f = pow( 1-s, reflectionParams.x );");
            //AddLine(b, "#else");
            //AddLine(b, "float f = 1 - pow( 1-s, reflectionParams.x );");
            //AddLine(b, "#endif");

            AddLine(b, "float f = 1 - pow( 1-s, reflectance );");

            //AddLine(b, "f = saturate(f * reflectionParams.y + reflectionParams.z);");
            AddLine(b, "vec3 r = xform( cViewIMtx, vec4( reflect( pipeline.ViewDir, pipeline.Normal ), 0 ) ).xyz;");
            AddLine(b, "vec4 envMap;");
            AddLine(b, "envMap = texCUBE(reflectionMapSamp, r);");
            //AddLine(b, "// dual-paraboloid mapping");
            //AddLine(b, "{");
            //AddLine(b, "    vec2 uv = r.xz;");
            //AddLine(b, "    float d;");
            //AddLine(b, "    if (r.y < 0.0f) d = 1.0f;");
            //AddLine(b, "    else d = -1.0f;");
            //AddLine(b, "    uv /= (d - r.y);");
            //AddLine(b, "    uv = uv * 0.5 + 0.5;");
            //AddLine(b, "    uv.x *= 0.5f;");
            //AddLine(b, "    if (r.y >= 0.0f)");
            //AddLine(b, "        uv.x += 0.5f;");
            //AddLine(b, "    envMap = tex2D(reflectionMapSamp, uv);");
            //AddLine(b, "}");

            AddLine(b, "pipeline.Reflection += envMap.rgb * f;");
        }
    }
}
